package com.pactera.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class ObjUtils {

    private ObjUtils() {
    }

    /**
     * 对象深度克隆
     *
     * @param obj 源对象
     * @author: liqingdian
     */
    public static <T extends Serializable> T clone(T obj) throws Exception {
        // 说明：调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源，这一点不同于对外部资源（如文件流）的释放
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(obj);
        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        return (T) ois.readObject();
    }

    /**
     * 对象转map
     *
     * @param obj 序列化对象
     * @author: liqingdian
     */
    public static <T> Map<String, Object> toMap(T obj) {
        if (obj == null) {
            return null;
        }
        String text = JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue);
        return JSON.parseObject(text, Map.class);
    }

    /**
     * 非空校验
     *
     * @param obj    对象
     * @param blank  字符串类型是否校验blank
     * @param fields 需要校验的字段，为空，校验全属性
     * @author: liqingdian
     */
    public static <T> void isNotNull(T obj, boolean blank, String... fields) {
        Map<String, Object> data = toMap(obj);
        Set<String> fieldSet;
        if (ArrayUtils.isNotEmpty(fields)) {
            fieldSet = Lists.newArrayList(fields).stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet());
        } else {
            fieldSet = data.keySet();
        }
        Object value;
        for (String field : fieldSet) {
            value = data.get(field);
            if (value instanceof String && blank) {
                Assert.isNotBlank((String) value, StrUtils.join("[", field, "]不能为空"));
            } else {
                Assert.isNotNull(value, StrUtils.join("[", field, "]不能为空"));
            }
        }
    }
}
